bl_info = {
    "name": "Move X Axis",
    "category": "Object",
}

PREFIX_U = 'u_r_'
PREFIX_V = 'v_r_'
PREFIX_RHO = 'rho_r_'
PATH = '/home/behollis/DATA/in/ts00050/'
DPATH = '/home/behollis/DATA/out/lockExSt/ts00050/'

import sys
#H5PY_SOURCE_DIR = '/usr/local/lib/python2.7/dist-packages/h5py-2.3.1-py2.7-linux-x86_64.egg'
#if H5PY_SOURCE_DIR not in sys.path:
#    sys.path.append(H5PY_SOURCE_DIR)

PATH = '/home/behollis/Dropbox/eurovis2015shortpaperCode/src/'#os.path.dirname(__file__)
if PATH not in sys.path:
   sys.path.append(PATH)
   
import loadStreamlines
import bpy
import h5py
#import pydevd
#import debugmaya
from loadStreamlines import readStreamlines
import interpProbDensity
from bpy_extras.io_utils import ImportHelper
import mathutils


prob = None
slines = None
MEM = 10

#
#    Store properties in the active scene
#
def initSceneProperties(scn):
    bpy.types.Scene.seed_x = bpy.props.IntProperty(
        name = 'X', 
        description = "X seed location")
    scn['seed_x'] = 30  
    
    bpy.types.Scene.seed_y = bpy.props.IntProperty(
        name = 'Y', 
        description = "Y seed location")
    scn['seed_y'] = 25
    
    bpy.types.Scene.seed_z = bpy.props.IntProperty(
        name = 'Z', 
        description = "Z seed location")
    scn['seed_z'] = 0
    
    bpy.types.Scene.members = bpy.props.IntProperty(
        name = 'Members', 
        description = 'Number of members')
    scn['members'] = 10
 
    return
 
initSceneProperties(bpy.context.scene)

#
#    Menu in UI region
#
class Hdf5ImportPanel(bpy.types.Panel):
    bl_label = 'KDE Streamlines'
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"
    
    def draw(self, context):
        
        layout = self.layout
 
        #layout.label('')
        row = layout.row(align=True)
        row.alignment = 'EXPAND'
        row.operator('h5py.load', text='import', icon='FILE_FOLDER')
        
        scn = context.scene
        layout.prop(scn, 'seed_x')
        layout.prop(scn, 'seed_y')
        layout.prop(scn, 'seed_z')
        layout.prop(scn, 'members')
        
        row = layout.row(align=True)
        row.operator("object.loadsls", text='load', icon='MESH_DATA')
        
        #row.operator("object.loadsls", icon='LAMP_DATA')
 
class OBJECT_OT_LoadHdf5Button(bpy.types.Operator, ImportHelper):
    #http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Blender_add-ons
    
    bl_idname = "h5py.load"
    bl_label = "Load hdf5 file"
 
    # From ImportHelper. Filter filenames.
    filename_ext = ".hdf5"
    filter_glob = bpy.props.StringProperty(default='*.hdf5', options={'HIDDEN'})
 
    filepath = bpy.props.StringProperty(name='File Path', maxlen=1024, default=DPATH)
 
    def execute(self, context):
        import os
        global prob, slines, MEM
    
        f = h5py.File(self.properties.filepath, 'r')
        
        seed_x = bpy.context.scene['seed_x']
        seed_y = bpy.context.scene['seed_y']
        seed_z = bpy.context.scene['seed_z']
        slines = readStreamlines(seed_x, seed_y, f)
        print('loaded {0} slines'.format(len(slines)))
        
        f.close()
        
        return{'FINISHED'}    
 
    def invoke(self, context, event):
        context.window_manager.fileselect_add(self)
        return {'RUNNING_MODAL'}    


class KDEStreamlines(bpy.types.Operator):
    ''' '''      # blender will use this as a tooltip for menu items and buttons.
    bl_idname = "object.loadsls"        # unique identifier for buttons and menu items to reference.
    bl_label = 'Load KDE Streamlines'         # display name  in the interface.
    bl_options = {'REGISTER', 'UNDO'}  # enable undo for the operator.

    def createNewStreamline(self, name):
        me = bpy.data.meshes.new(name)
        ob = bpy.data.objects.new(name, me)  
        
        # Link the object to the current scene and make it active. 
        # Optionally, we can make the newly created object active 
        # or selected. This code is the same for all kinds of objects.
        scn = bpy.context.scene
        scn.objects.link(ob)
        scn.objects.active = ob 
        
        return ob, me
    
    def findVerts(self, sl):
        verts = list()   
        for ptidx in range(0, len(sl[0])):
            vert = ( sl[0][ptidx], sl[1][ptidx], 0.0 )
            verts.append( vert )
            
        return verts
    
    def findEdges(self, sl):
        edges = list()
        for idx in range(1,len(sl[0])):
            edge = ( idx - 1, idx )
            edges.append( edge )
        
        return edges
    
    def addProbMaterial(self, slprobs, slobs, prob_list):
        ''' Adds material to each face of streamline quads based
        on cumulative density of velocities in field. '''
        
        bpy.ops.object.mode_set(mode='OBJECT')
        
        for idx in range(0,len(slobs)):
            ma = bpy.data.materials.new('sl'+str(idx+1))
            ma.diffuse_color[0] = 0.0 #r
            ma.diffuse_color[1] = 1.0 #g
            ma.diffuse_color[2] = 0.0 #b
            #scale intensity by fraction of maxium value
            intensity = ( slprobs[idx+1][0] - min(prob_list) ) / ( max(prob_list) - min(prob_list) )
            ma.diffuse_intensity = intensity
            ma.emit = 2.0 * intensity
            
            print('material intensity = {0}'.format( intensity ))
            
            slobs[idx].data.materials.append(ma)
            
            
    
    def extrudeEdges(self, slmesh, ob):
        ''' Extrudes edges to produce faces on either side of orthogonal direction to 
        streamline line segments. Note: Assumes streamlines are
        in the x-y plane with zero z component. '''
        
        bpy.ops.object.mode_set(mode='OBJECT')
        bpy.ops.object.editmode_toggle() 
        ob.select = True
    
        verts = slmesh.vertices#ob.data.vertices
        nverts = len(verts)
        
        for idx in range(0, nverts-1):
            v0 = verts[idx].co
            v1 = verts[idx+1].co
            segdir = v1 - v0
            
            kvec = mathutils.Vector((0.0,0.0,1.0)) #k unit vector
            ortho = segdir.cross(kvec)
            ortho.normalize()
            ortho *= 0.1 #scale dir of extrusionn
            
            # each segment produces two faces, 
            # extruded in oppposite directions
            #bpy.ops.object.mode_set(mode='OBJECT')
            
            # deselect all geometry
            #http://www.blender.org/api/blender_python_api_2_72b_release/bpy.ops.mesh.html
            #bpy.ops.object.mode_set(mode='OBJECT')
            #bpy.ops.object.select_all(action='DESELECT') 
            
            bpy.ops.object.mode_set(mode='EDIT')
            bpy.ops.mesh.select_all(action='DESELECT') 
            
            bpy.ops.object.mode_set(mode='OBJECT')
            ob.data.edges[idx].select = True
            bpy.ops.object.mode_set(mode='EDIT')
            
            # first face
            bpy.ops.mesh.extrude_edges_indiv(mirror=True) #not sure what mirror parameter does??
            #bpy.ops.mesh.extrude_edges_move() #not sure what mirror parameter does??
            bpy.ops.transform.translate(value=(ortho[0], ortho[1], ortho[2]), mirror = True)
            
            # second face
            #bpy.ops.mesh.extrude_edges_indiv(mirror=False) #not sure what mirror parameter does??
            #bpy.ops.transform.translate(ortho.negate())
            ob.data.edges[idx].select = False
            
            slmesh.update()
            
    
    def execute(self, context):        # execute() is called by blender when running the operator.
        
        global prob, slines, MEM
        
        MEM = bpy.context.scene['members'] 
        
        seed_x = bpy.context.scene['seed_x']
        seed_y = bpy.context.scene['seed_y']
        seed_z = bpy.context.scene['seed_z']
                
        slines_prob, prob_list = interpProbDensity.calcStreamlineProbs([seed_x, seed_y], slines, MEM+10)
        
        slines_obs = list()
        
        idx = 1
        for sl in slines[1:MEM]:
            ob, me = self.createNewStreamline('sl'+str(idx).zfill(3))
            idx += 1
            verts = self.findVerts(sl)  
            edges = self.findEdges(sl) 
            
            me.from_pydata( verts, edges, [] )
            me.update()
            bpy.context.scene.update() #make sure the mesh / object is in scene before changing modes
            
            print( 'Extruding streamline {0}'.format( str(idx) ) )
            self.extrudeEdges(me,ob)
            
            slines_obs.append(ob)
            
        self.addProbMaterial(slines_prob, slines_obs, prob_list[1:MEM])
            
        return {'FINISHED'}           # this lets blender  know the operator finished successfully.

def register(): 
    #bpy.utils.register_class(LoadKDEStreamlines)
    bpy.utils.register_module(__name__)


def unregister():
    #bpy.utils.unregister_class(LoadKDEStreamlines)
    bpy.utils.unregister_module(__name__)


# This allows you to run the script directly from blenders text editor
# to test the addon without having to install it.
if __name__ == "__main__":
    register()
